﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;

namespace UtilZ.Dotnet.Ex.Model
{
    /// <summary>
    /// 树表格节点基类
    /// </summary>
    public abstract class TreeDataGridNodeAbs : CheckItemShowAbs, ITreeDataGridNode
    {
        private ITreeDataGridNode _parent;
        /// <summary>
        /// 获取父节点
        /// </summary>
        public virtual ITreeDataGridNode Parent
        {
            get { return _parent; }
            set
            {
                _parent = value;
                base.OnRaisePropertyChanged(nameof(Parent));
            }
        }

        private double _nodeLocationOffset = 0d;
        /// <summary>
        /// 节点位置偏移,子节点相对父节点向右偏移量,单位/像素
        /// </summary>
        public virtual double NodeLocationOffset
        {
            get { return _nodeLocationOffset; }
            set
            {
                _nodeLocationOffset = value;
                base.OnRaisePropertyChanged(nameof(NodeLocationOffset));
            }
        }







        private bool _isChecked = false;
        /// <summary>
        /// 该项是否框选中
        /// </summary>
        public virtual bool IsChecked
        {
            get { return _isChecked; }
            set
            {
                if (_isChecked == value)
                {
                    return;
                }

                this.SetIsChecked(value);
                this.SetChildIsChecked(this.Nodes, value);
                this.SetParentIsChecked(this.Parent, value);
            }
        }

        /// <summary>
        /// 设置节点框选中
        /// </summary>
        /// <param name="isChecked"></param>
        public virtual void SetIsChecked(bool isChecked)
        {
            _isChecked = isChecked;
            base.OnRaisePropertyChanged(nameof(IsChecked));
        }

        private void SetParentIsChecked(ITreeDataGridNode taskItem, bool isChecked)
        {
            if (taskItem == null)
            {
                return;
            }

            if (isChecked)
            {
                if (taskItem.NodeCount > 0)
                {
                    int isCheckedCount = taskItem.Nodes.Count(t => { return t.IsChecked; });
                    if (isCheckedCount == taskItem.Nodes.Count)
                    {
                        taskItem.SetIsChecked(isChecked);
                        this.SetParentIsChecked(taskItem.Parent, isChecked);
                    }
                    else
                    {
                        taskItem.SetIsChecked(false);
                    }
                }
                else
                {
                    taskItem.SetIsChecked(isChecked);
                }
            }
            else
            {
                taskItem.SetIsChecked(isChecked);
                this.SetParentIsChecked(taskItem.Parent, isChecked);
            }
        }

        private void SetChildIsChecked(ObservableCollection<ITreeDataGridNode> nodes, bool isChecked)
        {
            if (nodes == null || nodes.Count == 0)
            {
                return;
            }

            foreach (ITreeDataGridNode taskItem in nodes)
            {
                taskItem.IsChecked = isChecked;
                this.SetChildIsChecked(taskItem.Nodes, isChecked);
            }
        }







        private bool _isExpanded = true;
        /// <summary>
        /// 获取一个值，用以指示树节点是否处于可展开状态[true:展开;false:关闭]
        /// </summary>
        public virtual bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                _isExpanded = value;
                base.OnRaisePropertyChanged(nameof(IsExpanded));

                bool subNodeIsShow;
                if (this._isExpanded && this._isShow)
                {
                    subNodeIsShow = true;
                }
                else
                {
                    subNodeIsShow = false;
                }

                this.SetNodesVisible(this._nodes, subNodeIsShow);
            }
        }

        private void SetNodesVisible(ObservableCollection<ITreeDataGridNode> nodes, bool isShow)
        {
            if (nodes == null)
            {
                return;
            }

            foreach (TreeDataGridNodeAbs node in nodes)
            {
                node.SetIsShow(isShow);

                if (isShow && !node.Visible)
                {
                    continue;
                }

                this.SetNodesVisible(node.Nodes, isShow);
            }
        }


        private bool _isShow = true;
        /// <summary>
        /// 表示该节点是否显示[true:显示;false:隐藏]
        /// </summary>
        private void SetIsShow(bool value)
        {
            bool visible;
            if (value && (this._parent == null || this._parent.IsExpanded))
            {
                visible = true;
            }
            else
            {
                visible = false;
            }

            this._isShow = value;
            this.Visible = visible;
        }


        private bool _visible = true;
        /// <summary>
        /// 由展开状态和节点显示状态决定本节点是否显示
        /// </summary>
        public virtual bool Visible
        {
            get
            {
                return _visible;
            }
            set
            {
                if (_visible == value)
                {
                    return;
                }

                _visible = value;
                base.OnRaisePropertyChanged(nameof(Visible));
            }
        }



        /// <summary>
        /// 树节点展开关闭标签是否显示
        /// </summary>
        public virtual bool TagVisible
        {
            get
            {
                if (this.NodeCount == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }

        /// <summary>
        /// 刷新树节点展开关闭标签是否显示
        /// </summary>
        protected void RefreshTagVisible()
        {
            base.OnRaisePropertyChanged(nameof(TagVisible));
        }

        private bool _allowEdit = false;
        /// <summary>
        /// 是否允许编辑
        /// </summary>
        public virtual bool AllowEdit
        {
            get { return _allowEdit; }
            set
            {
                _allowEdit = value;
                base.OnRaisePropertyChanged(nameof(AllowEdit));
            }
        }

        private ObservableCollection<ITreeDataGridNode> _nodes;
        /// <summary>
        /// 子节点集合
        /// </summary>
        public ObservableCollection<ITreeDataGridNode> Nodes
        {
            get { return _nodes; }
        }

        private void Value_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            this.RefreshTagVisible();
        }




        /// <summary>
        /// 获取子节点数
        /// </summary>
        public virtual int NodeCount
        {
            get
            {
                if (this._nodes == null)
                {
                    return 0;
                }

                return this._nodes.Count;
            }
        }

        /// <summary>
        /// 添加子节点
        /// </summary>
        /// <param name="node"></param>
        public virtual void AddNode(ITreeDataGridNode node)
        {
            if (node == null)
            {
                return;
            }

            if (this._nodes == null)
            {
                this._nodes = new ObservableCollection<ITreeDataGridNode>();
                this._nodes.CollectionChanged += Value_CollectionChanged;
            }

            this._nodes.Add((TreeDataGridNodeAbs)node);
            node.Parent = this;
            this.RefreshTagVisible();
        }

        /// <summary>
        /// 移除子节点
        /// </summary>
        /// <param name="node"></param>
        public virtual void RemoveNode(ITreeDataGridNode node)
        {
            if (this._nodes == null || node == null)
            {
                return;
            }

            this._nodes.Remove((TreeDataGridNodeAbs)node);
            node.Parent = null;
            this.RefreshTagVisible();
        }

        /// <summary>
        /// 移除当前节点
        /// </summary>
        public virtual void RemoveSelfNode()
        {
            if (this._parent != null)
            {
                this._parent.RemoveNode(this);
            }
        }

        /// <summary>
        /// 清空子节点
        /// </summary>
        public virtual void ClearNode()
        {
            if (this._nodes == null || this._nodes.Count == 0)
            {
                return;
            }

            this._nodes.Clear();
            this.RefreshTagVisible();
        }

        /// <summary>
        /// 重置显示节点
        /// </summary>
        public virtual void ResetNode()
        {
            this._visible = true;
            this._isShow = true;
            this._isExpanded = true;
        }

        /// <summary>
        /// 是否包含子节点
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public virtual bool Contains(ITreeDataGridNode node)
        {
            if (this._nodes == null ||
                this._nodes.Count == 0 ||
                node == null)
            {
                return false;
            }

            return this._nodes.Contains((TreeDataGridNodeAbs)node);
        }






        /// <summary>
        /// 构造函数初始化
        /// </summary>
        /// <param name="text">显示文本</param>
        /// <param name="nodeLocationOffset">节点位置偏移,子节点相对父节点向右偏移量,单位/像素</param>
        /// <param name="parent">父节点</param>
        public TreeDataGridNodeAbs(string text, double nodeLocationOffset, ITreeDataGridNode parent = null)
            : this(text, null, nodeLocationOffset, parent)
        {
            this._nodeLocationOffset = nodeLocationOffset;
        }

        /// <summary>
        /// 构造函数初始化
        /// </summary>
        /// <param name="text">显示文本</param>
        /// <param name="imageFilePath">图片路径</param>
        /// <param name="nodeLocationOffset">节点位置偏移,子节点相对父节点向右偏移量,单位/像素</param>
        /// <param name="parent">父节点</param>
        public TreeDataGridNodeAbs(string text, string imageFilePath, double nodeLocationOffset, ITreeDataGridNode parent = null)
              : base(text, imageFilePath)
        {
            this._parent = parent;
            if (parent != null)
            {
                parent.AddNode(this);
            }

            this._nodeLocationOffset = nodeLocationOffset;
        }
    }
}
